package main

import (
	"fmt"
	"os"
	"strings"
	"time"

	"github.com/sirupsen/logrus"
)

const (
	csUID = "Uid"
	csGID = "Gid"
	csCMD = "Cmd"

	format = "2006-01-02 15:04:05"
)

var level = [...]string{
	"PANIC",
	"FATAL",
	"ERROR",
	"WARNS",
	"INFOS",
	"DEBUG",
}

type ChannelFormatter struct {
	day      int
	level    int
	file     *os.File
	basename string
	pathname string
}

func NewChannelFormatter(name string, level int) *ChannelFormatter {
	pathname, basename := "", name
	for i := len(name) - 1; i > 0; i-- {
		if name[i] == '/' {
			pathname, basename = name[:i+1], name[i+1:]
			break
		}
	}

	year, month, day := time.Now().Date()
	filename := fmt.Sprintf("%s_%04d%02d%02d.log", basename, year, month, day)
	file, _ := os.OpenFile(pathname+filename, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)

	this := new(ChannelFormatter)
	this.pathname = pathname
	this.basename = basename
	this.level = level
	this.file = file
	this.day = day

	//logrus = logrus.New()
	logrus.SetLevel(logrus.Level(level))
	logrus.SetOutput(this.file)
	logrus.SetFormatter(this)
	logrus.AddHook(this)

	return this
}

func (this *ChannelFormatter) Format(entry *logrus.Entry) ([]byte, error) {
	data := []string{}
	data = append(data, entry.Time.Format(format))
	data = append(data, level[entry.Level])
	if v, ok := entry.Data[csUID]; ok {
		data = append(data, csUID+":"+v.(string))
	}
	if v, ok := entry.Data[csGID]; ok {
		data = append(data, csGID+":"+v.(string))
	}
	if v, ok := entry.Data[csCMD]; ok {
		data = append(data, v.(string))
	}
	data = append(data, entry.Message+"\n")

	return []byte(strings.Join(data, "|")), nil
}

func (this *ChannelFormatter) Levels() []logrus.Level {
	return logrus.AllLevels
}

func (this *ChannelFormatter) Fire(entry *logrus.Entry) error {
	now := time.Now()
	year, month, day := now.Date()
	if day != this.day {
		this.file.Close()
		filename := fmt.Sprintf("%s_%04d%02d%02d.log", this.basename, year, month, day)
		file, _ := os.OpenFile(this.pathname+filename, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		this.day = day
		this.file = file
		logrus.SetOutput(this.file)
	}
	return nil
}

func (this *ChannelFormatter) WithFields(fields logrus.Fields) *logrus.Entry {
	return logrus.WithFields(fields)
}

func main() {
	logmaker := NewChannelFormatter("logic", 5)

	logger := logmaker.WithFields(logrus.Fields{
		"Uid": "100012",
		"Gid": "1",
		"Cmd": "GET_USER_INFO",
	})

	logger.Info("Get User Info Begin")
	logger.Debug("User Comming Warning")
	logger.Warning("Get User Info Success")
}
